#ifndef FISHTHREAD_H_
#define FISHTHREAD_H_

#include <vector>
#include <list>
#include <set>

#include "fish.h"
#include "QuadTree.h"

class LeafNode;
class TreeNode;
class QuadTree;

typedef std::vector < fish_t > FishVector;
typedef std::set < LeafNode * >LeafSet;
typedef std::set < TreeNode * >TreeSet;

struct fishAndNode {
    fish_t *fish;
    LeafNode *node;
};
typedef std::vector < fishAndNode > fishAndNodeVector;

class FishThread
{
public:
    FishThread();
    virtual ~ FishThread();

    void addLeaf( LeafNode * );
    void removeLeaf( LeafNode * );
    void addRoot( TreeNode * );
    void removeRoot( TreeNode * );
    //remove false root nodes from the list
    void cleanupRoots();
    //clear the root and leaf node lists
    void clearRootsLeaves();
    void interactFish();
    void computeNorm();
    //compute new fish's position based on forces
    void moveFish( double dt, int myID );
    /* Apply reflective boundary conditions (fish bounce off walls). */
    void bounceFish( fish_t & fish );
    //actually move the fish that belong in other threads' quads
    void transferFish( int otherThread );
    /*
     * balances the quadtree by performing appropriate collapse() and splitUp()
     * calls
     */
    void balance();
    void outputFish( FILE * output_fp, const double t, const double dt,
                     int &count );

    double averageInteractions();

    static int NumThreads;
    static QuadTree *Root;

    double maxNorm;
    double cg_x, cg_y;
    int nFishOwned;

protected:

    std::vector < fishAndNodeVector * >movedFish;
    LeafSet leafNodes;
    TreeSet rootNodes;
};

#endif                          /*FISHTHREAD_H_ */
